using System;
using System.Collections.Generic;
using System.Text;

namespace EuropeEngulfed.NET
{
    class SupplySelectionMove : Move
    {
        PlayingPiece playingPieceToSetSupply;
        public enum supplyMoveType
        {
            supplyBySea,
            supplyBySpecialAction,
        }

        supplyMoveType moveType;
        GameController.SeaSupplySolution seaSupplySolution;
        MapInfo.RegionID regionSupplied;
        MapInfo.CountryID countrySpending;

        public MapInfo.RegionID RegionSupplied
        {
            get
            {
                return regionSupplied;
            }
        }

        public PlayingPiece PlayingPieceToSetSupply
        {
            get
            {
                return playingPieceToSetSupply;
            }

            set
            {
                playingPieceToSetSupply = value;
            }
        }

        public SupplySelectionMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, GameTurn.GameSubPhase gameSubPhase, MapInfo.RegionID regionSupplied, PlayingPiece playingPieceToSetSupply, GameController.SeaSupplySolution seaSupplySolution) 
            : base(gameDate,gamePhase,gameSubPhase)
        {
            moveType = supplyMoveType.supplyBySea;
            this.playingPieceToSetSupply = playingPieceToSetSupply;
            this.playingPieceToSetSupply.OutOfSupplyState = PlayingPiece.OOSState.OOS;
            this.seaSupplySolution = seaSupplySolution;
            this.regionSupplied = regionSupplied;
        }

        public SupplySelectionMove(GameTurn.GameDate gameDate, GameTurn.GamePhase gamePhase, GameTurn.GameSubPhase gameSubPhase, MapInfo.RegionID regionSupplied, MapInfo.CountryID countrySpending)
            : base(gameDate, gamePhase, gameSubPhase)
        {
            moveType = supplyMoveType.supplyBySpecialAction;
            this.regionSupplied = regionSupplied;
            this.countrySpending = countrySpending;
        }

        public bool IsCountryCoveredBySpecialAction(MapInfo.CountryID countrySpending, MapInfo.CountryID country)
        {
            switch(country)
            {
                case MapInfo.CountryID.Rumania:
                case MapInfo.CountryID.Bulgaria:
                case MapInfo.CountryID.Hungary:
                case MapInfo.CountryID.Finland:
                    return countrySpending == MapInfo.CountryID.Germany;
                case MapInfo.CountryID.FreeFrance:
                    return countrySpending == MapInfo.CountryID.USA;
            }

            return countrySpending == country;
        }

        protected override void ProcessMove(GameState gameState)
        {
            if(this.moveType == supplyMoveType.supplyBySpecialAction)
            {
                LandRegionState regionState = (LandRegionState)gameState.GetRegionState(this.RegionSupplied);
                for(int i = 0; regionState.GetBlockAt(i) != null; i++)
                {
                    Block block = (Block)regionState.GetBlockAt(i);
                    if(block.OutOfSupply)
                    {
                        if (IsCountryCoveredBySpecialAction(this.countrySpending, block.CountryOwner))
                        {
                            block.OutOfSupplyState = PlayingPiece.OOSState.InSupply;
                            //Limited supply means reduce by one strength
                            if (block.CurrentStrength > 1)
                                block.CurrentStrength--;
                            else
                            {
                                regionState.ReturnPlayingPieceToForcePool(gameState, block);
                            }
                        }
                    }
                }

                gameState.SpendSpecialAction(this.countrySpending);
            }
            else
            {
                LandRegionState regionState = (LandRegionState)gameState.GetRegionState(this.RegionSupplied);
                if (this.PlayingPieceToSetSupply is Block)
                {
                    for (int i = 0; regionState.GetBlockAt(i) != null; i++)
                    {
                        Block block = regionState.GetBlockAt(i);
                        if (block.Equals(this.PlayingPieceToSetSupply) && block.OutOfSupply)
                        {
                            block.OutOfSupplyState = PlayingPiece.OOSState.InSupply;
                            this.PlayingPieceToSetSupply = block;
                            break;
                        }
                    }
                }
                else
                {
                    for (int i = 0; regionState.GetGSUAt(i) != null; i++)
                    {
                        GroundSupportUnit GSU = regionState.GetGSUAt(i);
                        if (GSU.Equals(this.PlayingPieceToSetSupply) && GSU.OutOfSupply)
                        {
                            GSU.OutOfSupplyState = PlayingPiece.OOSState.InSupply;
                            this.PlayingPieceToSetSupply = GSU;
                            break;
                        }
                    }
                }
            }
        }

        public override bool IsLegal(IGameStateInfoProvider gameStateInfoProvider, ref string ruleString)
        {
            return true;
        }

        public override System.Xml.XmlNode Serialise(System.Xml.XmlDocument xml)
        {
            System.Xml.XmlNode playingPieceToSetSupplyNode = xml.CreateElement("playingPieceToSetSupply");
            System.Xml.XmlNode seaSupplySolutionNode = xml.CreateElement("seaSupplySolution");
            System.Xml.XmlNode nodeToReturn = xml.CreateElement("Move");
            System.Xml.XmlAttribute typeAttr = xml.CreateAttribute("Type");
            System.Xml.XmlAttribute moveTypeAttr = xml.CreateAttribute("moveType");
            System.Xml.XmlAttribute regionSuppliedAttr = xml.CreateAttribute("regionSupplied");
            System.Xml.XmlAttribute countrySpendingAttr = xml.CreateAttribute("countrySpending");

            nodeToReturn.AppendChild(gameTurn.Serialise(xml));
            typeAttr.Value = this.GetType().ToString();
            moveTypeAttr.Value = Enum.GetName(moveType.GetType(), moveType);
            regionSuppliedAttr.Value = Enum.GetName(regionSupplied.GetType(), regionSupplied);
            countrySpendingAttr.Value = Enum.GetName(countrySpending.GetType(), countrySpending);

            if (this.playingPieceToSetSupply is Block)
                playingPieceToSetSupplyNode.AppendChild(((Block)playingPieceToSetSupply).Serialise(xml));
            else if (this.playingPieceToSetSupply is GroundSupportUnit)
                playingPieceToSetSupplyNode.AppendChild(((GroundSupportUnit)playingPieceToSetSupply).Serialise(xml));
            nodeToReturn.AppendChild(playingPieceToSetSupplyNode);

            nodeToReturn.Attributes.Append(typeAttr);
            nodeToReturn.Attributes.Append(moveTypeAttr);
            nodeToReturn.Attributes.Append(regionSuppliedAttr);
            nodeToReturn.Attributes.Append(countrySpendingAttr);

            System.Xml.XmlAttribute fromBeachHeadAttr = xml.CreateAttribute("fromBeachHead");
            fromBeachHeadAttr.Value = this.seaSupplySolution.fromBeachHead.ToString();
            seaSupplySolutionNode.Attributes.Append(fromBeachHeadAttr);
            if(this.seaSupplySolution.seaRegionPath != null)
            {
                foreach (SeaRegion seaRegion in this.seaSupplySolution.seaRegionPath)
                {
                    System.Xml.XmlNode seaRegionNode = xml.CreateElement("seaRegion");
                    seaRegionNode.InnerText = Enum.GetName(seaRegion.RegionID.GetType(), seaRegion.RegionID);
                    seaSupplySolutionNode.AppendChild(seaRegionNode);
                }
            }
            nodeToReturn.AppendChild(seaSupplySolutionNode);

            return nodeToReturn;
        }

        public new static Move Deserialise(System.Xml.XmlNode node)
        {
            if (node.Attributes["Type"].Value == typeof(SupplySelectionMove).ToString() && node.Name == "Move")
            {
                System.Xml.XmlNode seaSupplySolutionNode = node.SelectSingleNode("seaSupplySolution");
                GameTurn parsedGameTurn = GameTurn.Deserialise(node.SelectSingleNode("GameTurn"));
                SupplySelectionMove supplySelectionMoveToReturn = new SupplySelectionMove(parsedGameTurn.CurrentGameDate, parsedGameTurn.CurrentGamePhase, parsedGameTurn.CurrentGameSubPhase, (MapInfo.RegionID)Enum.Parse(typeof(MapInfo.RegionID), node.Attributes["regionSupplied"].Value), (MapInfo.CountryID)Enum.Parse(typeof(MapInfo.CountryID), node.Attributes["countrySpending"].Value));
                supplySelectionMoveToReturn.moveType = (supplyMoveType)Enum.Parse(typeof(supplyMoveType), node.Attributes["moveType"].Value);
                if (supplySelectionMoveToReturn.moveType != supplyMoveType.supplyBySpecialAction)
                {
                    supplySelectionMoveToReturn.playingPieceToSetSupply = PlayingPiece.Deserialise(node.SelectSingleNode("playingPieceToSetSupply"));
                    supplySelectionMoveToReturn.seaSupplySolution.fromBeachHead = bool.Parse(seaSupplySolutionNode.Attributes["fromBeachHead"].Value);
                    supplySelectionMoveToReturn.seaSupplySolution.seaRegionPath = new List<SeaRegion>();
                    foreach (System.Xml.XmlNode seaSupplyPath in seaSupplySolutionNode)
                    {
                        supplySelectionMoveToReturn.seaSupplySolution.seaRegionPath.Add((SeaRegion)MapInfo.GetRegion((MapInfo.RegionID)Enum.Parse(typeof(MapInfo.RegionID), seaSupplyPath.InnerText)));
                    }
                }

                return supplySelectionMoveToReturn;
            }
            else
                throw new InvalidOperationException();
        }

        public override System.Windows.Forms.TreeNode GetMoveTreeNode(System.Windows.Forms.TreeView treeView)
        {
            if (this.moveType == supplyMoveType.supplyBySpecialAction)
                return new System.Windows.Forms.TreeNode("Units in " + MapInfo.GetRegionName(this.regionSupplied) + " supplied by special action (limited supply)");
            else
                return new System.Windows.Forms.TreeNode("Unit in " + MapInfo.GetRegionName(this.regionSupplied) + " supplied by sea");
        }

        public override string GetStringForNetworkMessage()
        {
            if(this.moveType == supplyMoveType.supplyBySpecialAction)
            {
                return "Special Action spent for limited supply in " + Enum.GetName(typeof(MapInfo.RegionID), this.regionSupplied) + " by " + Enum.GetName(typeof(MapInfo.CountryID), this.countrySpending);
            }
            else
            {
                return "";
            }
        }
    }
}
